home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / tde3.zip / DIFF.C < prev    next >
C/C++ Source or Header  |  1993-06-05  |  24KB  |  733 lines

  1. /*
  2.  * Being that the windows in TDE are numbered and lettered, we can easily
  3.  * prompt for windows to diff.  Might as well do a few standard diff
  4.  * options:  ignore leading space, ignore all space, ignore blank lines,
  5.  * ignore end-of-line, and Ignore/Match case.  Once the diff is defined,
  6.  * just press one key to find the next diff.  Any two visible windows may
  7.  * be diffed, which is really nice for comparing similar functions or
  8.  * data in seperate areas of a file.
  9.  *
  10.  *
  11.  * New editor name:  TDE, the Thomson-Davis Editor.
  12.  * Author:           Frank Davis
  13.  * Date:             June 5, 1991, version 1.0
  14.  * Date:             July 29, 1991, version 1.1
  15.  * Date:             October 5, 1991, version 1.2
  16.  * Date:             January 20, 1992, version 1.3
  17.  * Date:             February 17, 1992, version 1.4
  18.  * Date:             April 1, 1992, version 1.5
  19.  * Date:             June 5, 1992, version 2.0
  20.  * Date:             October 31, 1992, version 2.1
  21.  * Date:             April 1, 1993, version 2.2
  22.  * Date:             June 5, 1993, version 3.0
  23.  *
  24.  * This code is released into the public domain, Frank Davis.
  25.  * You may distribute it freely.
  26.  */
  27.  
  28. #include "tdestr.h"
  29. #include "common.h"
  30. #include "define.h"
  31. #include "tdefunc.h"
  32.  
  33.  
  34. /*
  35.  * Name:    define_diff
  36.  * Purpose: get info needed to initialize diff
  37.  * Date:    October 31, 1992
  38.  * Passed:  window:  pointer to current window
  39.  * Notes:   allow the user to start the diff at the beginning of the
  40.  *            file or at the current cursor location.  once the diff
  41.  *            has been defined, the user may press one key to diff again.
  42.  *          user may diff any two visible windows on the screen.
  43.  */
  44. int  define_diff( WINDOW *window )
  45. {
  46. int  rc;
  47. char temp[MAX_COLS];
  48. int  num1;
  49. int  let1;
  50. int  num2;
  51. int  let2;
  52. int  start;
  53. char line_buff[(MAX_COLS+1)*2];  /* buffer for char and attribute  */
  54. char buff[MAX_COLS*2];           /* buffer for char and attribute  */
  55.  
  56.    /*
  57.     * get window number and letter of the first diff window.  then,
  58.     *   verify that window - does it exit? is it visible?
  59.     */
  60.    *temp = '\0';
  61.    rc = get_name( diff_prompt1, window->bottom_line, temp,
  62.                   g_display.message_color );
  63.    if (rc == OK) {
  64.       rc = verify_number( temp, &num1 );
  65.       if (rc == OK)
  66.          rc = verify_letter( temp, &let1, &diff.w1 );
  67.    } else
  68.       return( ERROR );
  69.    if (rc == ERROR) {
  70.       combine_strings( buff, diff_prompt6a, temp, diff_prompt6b );
  71.       error( WARNING, window->bottom_line, buff );
  72.       return( ERROR );
  73.    }
  74.  
  75.    /*
  76.     * get and verify the next window number and letter to diff.
  77.     */
  78.    *temp = '\0';
  79.    rc = get_name( diff_prompt2, window->bottom_line, temp,
  80.                   g_display.message_color );
  81.    if (rc == OK) {
  82.       rc = verify_number( temp, &num2 );
  83.       if (rc == OK)
  84.          rc = verify_letter( temp, &let2, &diff.w2 );
  85.    } else
  86.       return( ERROR );
  87.    if (rc == ERROR) {
  88.       combine_strings( buff, diff_prompt6a, temp, diff_prompt6b );
  89.       error( WARNING, window->bottom_line, buff );
  90.       return( ERROR );
  91.    }
  92.  
  93.    /*
  94.     * are leading spaces significant?
  95.     */
  96.    save_screen_line( 0, window->bottom_line, line_buff );
  97.    set_prompt( diff_prompt7a, window->bottom_line );
  98.    start = get_yn( );
  99.    restore_screen_line( 0, window->bottom_line, line_buff );
  100.    if (start != ERROR)
  101.       diff.leading =  start == A_YES ?  TRUE  :  FALSE;
  102.    else
  103.       return( ERROR );
  104.  
  105.    /*
  106.     * are all spaces significant?
  107.     */
  108.    save_screen_line( 0, window->bottom_line, line_buff );
  109.    set_prompt( diff_prompt7b, window->bottom_line );
  110.    start = get_yn( );
  111.    restore_screen_line( 0, window->bottom_line, line_buff );
  112.    if (start != ERROR) {
  113.       if (start == A_YES)
  114.          diff.leading = diff.all_space = TRUE;
  115.       else
  116.          diff.all_space = FALSE;
  117.    } else
  118.       return( ERROR );
  119.  
  120.    /*
  121.     * are blank lines significant?
  122.     */
  123.    save_screen_line( 0, window->bottom_line, line_buff );
  124.    set_prompt( diff_prompt7c, window->bottom_line );
  125.    start = get_yn( );
  126.    restore_screen_line( 0, window->bottom_line, line_buff );
  127.    if (start != ERROR)
  128.       diff.blank_lines =  start == A_YES  ?  TRUE : FALSE;
  129.    else
  130.       return( ERROR );
  131.  
  132.    /*
  133.     * is end of line significant?
  134.     */
  135.    save_screen_line( 0, window->bottom_line, line_buff );
  136.    set_prompt( diff_prompt7d, window->bottom_line );
  137.    start = get_yn( );
  138.    restore_screen_line( 0, window->bottom_line, line_buff );
  139.    if (start != ERROR)
  140.       diff.ignore_eol =  start == A_YES  ?  TRUE : FALSE;
  141.    else
  142.       return( ERROR );
  143.  
  144.    /*
  145.     * now, find out were to start the diff -- beginning of file or
  146.     *   current cursor location.
  147.     */
  148.    save_screen_line( 0, window->bottom_line, line_buff );
  149.    set_prompt( diff_prompt3, window->bottom_line );
  150.    start = get_bc( );
  151.    restore_screen_line( 0, window->bottom_line, line_buff );
  152.  
  153.    if (start != ERROR) {
  154.       entab_linebuff( );
  155.       if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  156.          return( ERROR );
  157.  
  158.       /*
  159.        * if everything is everything, initialize the diff pointers.
  160.        */
  161.       diff.defined = TRUE;
  162.       if (start == BEGINNING) {
  163.          diff.d1 = diff.w1->file_info->line_list;
  164.          diff.d2 = diff.w2->file_info->line_list;
  165.          diff.rline1 = 1L;
  166.          diff.rline2 = 1L;
  167.          diff.bin_offset1 = 0;
  168.          diff.bin_offset2 = 0;
  169.          rc = differ( 0, 0, window->bottom_line );
  170.       } else {
  171.          diff.d1 = diff.w1->ll;
  172.          diff.d2 = diff.w2->ll;
  173.          diff.rline1 = diff.w1->rline;
  174.          diff.rline2 = diff.w2->rline;
  175.          diff.bin_offset1 = diff.w1->bin_offset;
  176.          diff.bin_offset2 = diff.w2->bin_offset;
  177.          rc = differ( diff.w1->rcol, diff.w2->rcol, window->bottom_line );
  178.       }
  179.    }
  180.    return( rc );
  181. }
  182.  
  183.  
  184. /*
  185.  * Name:    repeat_diff
  186.  * Purpose: compare two cursor positions
  187.  * Date:    October 31, 1992
  188.  * Passed:  window:  pointer to current window
  189.  * Notes:   user may press this key at any time once the diff has been
  190.  *            defined.
  191.  */
  192. int  repeat_diff( WINDOW *window )
  193. {
  194. register int rc = ERROR;
  195.  
  196.    if (diff.defined) {
  197.       entab_linebuff( );
  198.       if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  199.          return( ERROR );
  200.  
  201.       /*
  202.        * initialize the diff pointers.
  203.        */
  204.       diff.d1 = diff.w1->ll;
  205.       diff.d2 = diff.w2->ll;
  206.       diff.rline1 = diff.w1->rline;
  207.       diff.rline2 = diff.w2->rline;
  208.       diff.bin_offset1 = diff.w1->bin_offset;
  209.       diff.bin_offset2 = diff.w2->bin_offset;
  210.       rc = differ( diff.w1->rcol, diff.w2->rcol, window->bottom_line );
  211.    } else
  212.       error( WARNING, window->bottom_line, diff_prompt5 );
  213.    return( rc );
  214. }
  215.  
  216.  
  217. /*
  218.  * Name:    differ
  219.  * Purpose: diff text pointers
  220.  * Date:    October 31, 1992
  221.  * Passed:  initial_rcol1:  beginning column to begin diff in window1
  222.  *          initial_rcol2:  beginning column to begin diff in window2
  223.  *          bottom:         line to display diagnostics
  224.  * Notes:   a straight diff on text pointers is simple; however, diffing
  225.  *            with leading spaces and tabs is kinda messy.  let's do the
  226.  *            messy diff.
  227.  */
  228. int  differ( int initial_rcol1, int initial_rcol2, int bottom )
  229. {
  230. int  rcol1;             /* virtual real column on diff window 1 */
  231. int  rcol2;             /* virtual real column on diff window 2 */
  232. int  r1;                /* real real column rcol1 - needed for tabs */
  233. int  r2;                /* real real column rcol2 - needed for tabs */
  234. char c1;                /* character under r1 */
  235. char c2;                /* character under r2 */
  236. int  leading1;          /* adjustment for leading space in window 1 */
  237. int  leading2;          /* adjustment for leading space in window 2 */
  238. int  len1;              /* length of diff1 line */
  239. int  len2;              /* length of diff2 line */
  240. line_list_ptr node1;    /* scratch node in window 1 */
  241. line_list_ptr node2;    /* scratch node in window 2 */
  242. text_ptr diff1;         /* scratch text ptr in window 1 */
  243. text_ptr diff2;         /* scratch text ptr in window 2 */
  244. long rline1;            /* real line number of diff pointer 1 */
  245. long rline2;            /* real line number of diff pointer 2 */
  246. long bin_offset1;       /* binary offset of diff pointer 1 */
  247. long bin_offset2;       /* binary offset of diff pointer 2 */
  248. int  len;               /* line length variable */
  249. register int tabs;      /* local variable for mode.inflate_tabs, T or F */
  250. char line_buff[(MAX_COLS+1)*2];  /* buffer for char and attribute  */
  251.  
  252.    /*
  253.     * initialize the text pointers and the initial column.  skip any
  254.     *  initial blank lines.
  255.     */
  256.    rline1 = diff.rline1;
  257.    rline2 = diff.rline2;
  258.    node1 = diff.d1;
  259.    node2 = diff.d2;
  260.    bin_offset1 = diff.bin_offset1;
  261.    bin_offset2 = diff.bin_offset2;
  262.    tabs  = mode.inflate_tabs;
  263.    if (diff.blank_lines) {
  264.       while (node1->len != EOF  && is_line_blank( node1->line, node1->len )) {
  265.          bin_offset1 += node1->len;
  266.          node1 = node1->next;
  267.          ++rline1;
  268.          initial_rcol1 = 0;
  269.       }
  270.       while (node2->len != EOF  && is_line_blank( node2->line , node2->len)) {
  271.          bin_offset2 += node2->len;
  272.          node2 = node2->next;
  273.          ++rline2;
  274.          initial_rcol2 = 0;
  275.       }
  276.    }
  277.  
  278.    /*
  279.     * if everything is everything, initialize the diff variables and diff.
  280.     */
  281.    if (node1->len != EOF  &&  node2->len != EOF) {
  282.       diff1 = node1->line;
  283.       diff2 = node2->line;
  284.       rcol1 = initial_rcol1;
  285.       rcol2 = initial_rcol2;
  286.       len1  = node1->len;
  287.       len2  = node2->len;
  288.  
  289.       assert( rcol1 >= 0 );
  290.       assert( rcol1 < MAX_LINE_LENGTH );
  291.       assert( rcol2 >= 0 );
  292.       assert( rcol2 < MAX_LINE_LENGTH );
  293.       assert( len1 >= 0 );
  294.       assert( len1 < MAX_LINE_LENGTH );
  295.       assert( len2 >= 0 );
  296.       assert( len2 < MAX_LINE_LENGTH );
  297.  
  298.       /*
  299.        * if cursors are past EOL, move them back to EOL.
  300.        */
  301.       len = find_end( diff1, len1 );
  302.       if (rcol1 > len)
  303.          rcol1 = len;
  304.       len = find_end( diff2, len2 );
  305.       if (rcol2 > len)
  306.          rcol2 = len;
  307.  
  308.       /*
  309.        * if skip leading space, make sure our cursors start on first non-space.
  310.        */
  311.       if (diff.leading) {
  312.          leading1 = skip_leading_space( diff1, len1 );
  313.          leading2 = skip_leading_space( diff2, len2 );
  314.          if (tabs) {
  315.             leading1 = detab_adjust_rcol( diff1, leading1 );
  316.             leading2 = detab_adjust_rcol( diff2, leading2 );
  317.          }
  318.          if (rcol1 < leading1)
  319.             rcol1 = leading1;
  320.          if (rcol2 < leading2)
  321.             rcol2 = leading2;
  322.       }
  323.  
  324.       /*
  325.        * we now have a valid rcol for the diff start, we may need to adjust
  326.        *   for tabs, though.
  327.        */
  328.       assert( rcol1 >= 0 );
  329.       assert( rcol1 < MAX_LINE_LENGTH );
  330.       assert( rcol2 >= 0 );
  331.       assert( rcol2 < MAX_LINE_LENGTH );
  332.  
  333.       r1 =  tabs ? entab_adjust_rcol( diff1, len1, rcol1 ) : rcol1;
  334.       r2 =  tabs ? entab_adjust_rcol( diff2, len2, rcol2 ) : rcol2;
  335.  
  336.       assert( r1 >= 0 );
  337.       assert( r1 <= len1 );
  338.       assert( r2 >= 0 );
  339.       assert( r2 <= len2 );
  340.       assert( r1 <= rcol1 );
  341.       assert( r2 <= rcol2 );
  342.  
  343.       s_output( diff_message, g_display.mode_line, 67, g_display.diag_color );
  344.       while (node1->len != EOF  &&  node2->len != EOF  &&
  345.                          !g_status.control_break) {
  346.  
  347.          /*
  348.           * look at each character in each diff window
  349.           */
  350.          c1 = (char)(r1 < len1 ? *(diff1 + r1)  : 0);
  351.          c2 = (char)(r2 < len2 ? *(diff2 + r2)  : 0);
  352.  
  353.          /*
  354.           *  tabs == space
  355.           */
  356.          if (tabs) {
  357.             if (c1 == '\t')
  358.                c1 = ' ';
  359.             if (c2 == '\t')
  360.                c2 = ' ';
  361.          }
  362.  
  363.          /*
  364.           * skip spaces, if needed
  365.           */
  366.          if (diff.all_space) {
  367.             while (c1 == ' '  &&  r1 < len1) {
  368.                ++rcol1;
  369.                r1 = tabs ? entab_adjust_rcol( diff1, len1, rcol1 ) : rcol1;
  370.                c1 =  (char)(r1 < len1  ?  *(diff1 + r1) :  0);
  371.                if (c1 == '\t'  &&  tabs)
  372.                   c1 = ' ';
  373.             }
  374.             while (c2 == ' '  &&  r2 < len2) {
  375.                ++rcol2;
  376.                r2 = tabs ? entab_adjust_rcol( diff2, len2, rcol2 ) : rcol2;
  377.                c2 =  (char)(r2 < len2  ? *(diff2 + r2) : 0);
  378.                if (c2 == '\t'  &&  tabs)
  379.                   c2 = ' ';
  380.             }
  381.          }
  382.  
  383.          /*
  384.           * if one of the node pointers has come to EOL, move to next
  385.           *   diff line.
  386.           */
  387.          if (diff.ignore_eol) {
  388.             if (r1 >= len1) {
  389.                node1 = skip_eol( node1, &r1, &rcol1, &rline1, &bin_offset1 );
  390.                len1  = node1->len;
  391.                if (len1 != EOF) {
  392.                   diff1 = node1->line;
  393.                   c1 =  (char)(r1 < len1  ?  *(diff1 + r1) : 0);
  394.                   if (c1 == '\t'  &&  tabs)
  395.                      c1 = ' ';
  396.                }
  397.             }
  398.             if (r2 >= len2) {
  399.                node2 = skip_eol( node2, &r2, &rcol2, &rline2, &bin_offset2 );
  400.                len2  = node2->len;
  401.                if (len2 != EOF) {
  402.                   diff2 = node2->line;
  403.                   c2 =  (char)(r2 < len2  ? *(diff2 + r2)  :  0);
  404.                   if (c2 == '\t'  &&  tabs)
  405.                      c2 = ' ';
  406.                }
  407.             }
  408.          }
  409.  
  410.          /*
  411.           * convert the characters to lower case, if needed.
  412.           */
  413.          if (mode.search_case == IGNORE) {
  414.             c1 = (char)tolower( c1 );
  415.             c2 = (char)tolower( c2 );
  416.          }
  417.  
  418.          /*
  419.           * diff each character in the diff lines until we reach EOL
  420.           */
  421.          while (r1 < len1  && r2 < len2) {
  422.             if (c1 == c2) {
  423.                if (diff.all_space) {
  424.                   do {
  425.                      ++rcol1;
  426.                      r1 = tabs ? entab_adjust_rcol( diff1,len1,rcol1 ) : rcol1;
  427.                      c1 =  (char)(r1 < len1  ?  *(diff1 + r1)  :  0);
  428.                      if (c1 == '\t'  &&  tabs)
  429.                         c1 = ' ';
  430.                   } while (c1 == ' '  &&  r1 < len1);
  431.                   do {
  432.                      ++rcol2;
  433.                      r2 = tabs ? entab_adjust_rcol( diff2,len2,rcol2 ) : rcol2;
  434.                      c2 =  (char)(r2 < len2  ?  *(diff2 + r2)  :  0);
  435.                      if (c2 == '\t'  &&  tabs)
  436.                         c2 = ' ';
  437.                   } while (c2 == ' '  &&  r2 < len2);
  438.                } else {
  439.                   ++rcol1;
  440.                   ++rcol2;
  441.                   r1 = tabs ? entab_adjust_rcol( diff1, len1, rcol1 ) : rcol1;
  442.                   r2 = tabs ? entab_adjust_rcol( diff2, len2, rcol2 ) : rcol2;
  443.                   c1 =  (char)(r1 < len1  ?  *(diff1 + r1)  :  0);
  444.                   c2 =  (char)(r2 < len2  ?  *(diff2 + r2)  :  0);
  445.                   if (tabs) {
  446.                      if (c1 == '\t')
  447.                         c1 = ' ';
  448.                      if (c2 == '\t')
  449.                         c2 = ' ';
  450.                   }
  451.                }
  452.                if (diff.ignore_eol) {
  453.                   if (r1 >= len1) {
  454.                      node1 = skip_eol(node1, &r1, &rcol1, &rline1,&bin_offset1);
  455.                      len1  = node1->len;
  456.                      if (len1 != EOF) {
  457.                         diff1 = node1->line;
  458.                         c1 =  (char)(r1 < len1  ?  *(diff1 + r1)  : 0);
  459.                         if (c1 == '\t'  &&  tabs)
  460.                            c1 = ' ';
  461.                      }
  462.                   }
  463.                   if (r2 >= len2) {
  464.                      node2 = skip_eol(node2, &r2, &rcol2, &rline2,&bin_offset2);
  465.                      len2  = node2->len;
  466.                      if (len2 != EOF) {
  467.                         diff2 = node2->line;
  468.                         c2 = (char)(r2 < len2  ? *(diff2 + r2)  :  0);
  469.                         if (c2 == '\t'  &&  tabs)
  470.                            c2 = ' ';
  471.                      }
  472.                   }
  473.                }
  474.                if (mode.search_case == IGNORE) {
  475.                   c1 = (char)tolower( c1 );
  476.                   c2 = (char)tolower( c2 );
  477.                }
  478.             } else {
  479.  
  480.                /*
  481.                 * when we show the diff, use rcol1 and rcol2, as
  482.                 *   find_adjust does not adjust rcol for tabs.
  483.                 */
  484.                update_line( diff.w1 );
  485.                diff.w1->bin_offset = bin_offset1;
  486.                find_adjust( diff.w1, node1, rline1, rcol1 );
  487.                check_virtual_col( diff.w1, rcol1, rcol1 );
  488.                show_diff_window( diff.w1 );
  489.                update_line( diff.w2 );
  490.                diff.w2->bin_offset = bin_offset2;
  491.                bin_offset_adjust( diff.w2, rline2 );
  492.                find_adjust( diff.w2, node2, rline2, rcol2 );
  493.                check_virtual_col( diff.w2, rcol2, rcol2 );
  494.                show_diff_window( diff.w2 );
  495.                s_output( diff_blank, g_display.mode_line, 67,
  496.                          g_display.mode_color );
  497.                return( OK );
  498.             }
  499.          }
  500.  
  501.          /*
  502.           * if we haven't come to the end of a file buffer, check the last
  503.           *   characters.  see if pointers are at EOL.
  504.           */
  505.          if (node1->len != EOF && node2->len != EOF) {
  506.             if (rcol1 != len1  &&  rcol2 != len2) {
  507.                update_line( diff.w1 );
  508.                diff.w1->bin_offset = bin_offset1;
  509.                find_adjust( diff.w1, node1, rline1, rcol1 );
  510.                show_diff_window( diff.w1 );
  511.                update_line( diff.w2 );
  512.                diff.w2->bin_offset = bin_offset2;
  513.                find_adjust( diff.w2, node2, rline2, rcol2 );
  514.                show_diff_window( diff.w2 );
  515.                s_output( diff_blank, g_display.mode_line, 67,
  516.                          g_display.mode_color );
  517.                return( OK );
  518.             } else {
  519.                node1 = skip_eol( node1, &r1, &rcol1, &rline1, &bin_offset1 );
  520.                len1  = node1->len;
  521.                diff1 = node1->line;
  522.                node2 = skip_eol( node2, &r2, &rcol2, &rline2, &bin_offset2 );
  523.                len2  = node2->len;
  524.                diff2 = node2->line;
  525.             }
  526.          }
  527.  
  528.          assert( rcol1 >= 0 );
  529.          assert( rcol1 < MAX_LINE_LENGTH );
  530.          assert( rcol2 >= 0 );
  531.          assert( rcol2 < MAX_LINE_LENGTH );
  532.          assert( r1 >= 0 );
  533.          assert( r1 < MAX_LINE_LENGTH );
  534.          assert( r2 >= 0 );
  535.          assert( r2 < MAX_LINE_LENGTH );
  536.          assert( r1 <= rcol1 );
  537.          assert( r2 <= rcol2 );
  538.          if (node1->len == EOF)
  539.             assert( len1 == EOF );
  540.          else {
  541.             assert( len1 >= 0 );
  542.             assert( len1 < MAX_LINE_LENGTH );
  543.          }
  544.          if (node2->len == EOF)
  545.             assert( len2 == EOF );
  546.          else {
  547.             assert( len2 >= 0 );
  548.             assert( len2 < MAX_LINE_LENGTH );
  549.          }
  550.       }
  551.       save_screen_line( 0, bottom, line_buff );
  552.       set_prompt( diff_prompt4, bottom );
  553.       getkey( );
  554.       restore_screen_line( 0, bottom, line_buff );
  555.       s_output( diff_blank, g_display.mode_line, 67, g_display.mode_color );
  556.    }
  557.    return( ERROR );
  558. }
  559.  
  560.  
  561. /*
  562.  * Name:    skip_leading_space
  563.  * Purpose: put the diff on the first non-blank character
  564.  * Date:    October 31, 1992
  565.  * Passed:  s:  the string to search
  566.  *          len: length of string
  567.  * Returns: the first non-blank column
  568.  */
  569. int  skip_leading_space( text_ptr s, int len )
  570. {
  571. register int count = 0;
  572.  
  573.    assert( len >= 0 );
  574.    assert( len < MAX_LINE_LENGTH );
  575.  
  576.    if (s != NULL) {
  577.       if (mode.inflate_tabs) {
  578.          while (len > 0  &&  (*s == ' ' || *s == '\t')) {
  579.             ++count;
  580.             ++s;
  581.             --len;
  582.          }
  583.       } else {
  584.          while (len > 0  &&  *s == ' ') {
  585.            ++count;
  586.            ++s;
  587.            --len;
  588.          }
  589.       }
  590.    }
  591.    if (len == 0)
  592.       count = 0;
  593.    return( count );
  594. }
  595.  
  596.  
  597. /*
  598.  * Name:    skip_eol
  599.  * Purpose: move the diff to the next line
  600.  * Date:    October 31, 1992
  601.  * Passed:  d:           pointer to current node
  602.  *          r:           tab adjusted real col
  603.  *          rcol:        real real col
  604.  *          rline:       current line number
  605.  *          bin_offset:  offset from the beginning of the file
  606.  * Returns: next non-blank node
  607.  */
  608. line_list_ptr skip_eol( line_list_ptr d, int *r, int *rcol, long *rline,
  609.                         long *bin_offset )
  610. {
  611. int  leading;
  612. long rl;
  613. long bo;
  614.  
  615.    *r = *rcol = 0;
  616.    rl = *rline;
  617.    bo = *bin_offset;
  618.    if (d->len != EOF) {
  619.       bo += d->len;
  620.       d = d->next;
  621.       ++rl;
  622.       if (diff.blank_lines) {
  623.          while (d->len != EOF  &&  is_line_blank( d->line, d->len )) {
  624.             bo += d->len;
  625.             d = d->next;
  626.             ++rl;
  627.          }
  628.       }
  629.       if (d->len != EOF) {
  630.          if (diff.leading) {
  631.             leading = skip_leading_space( d->line, d->len );
  632.             if (mode.inflate_tabs)
  633.                leading = detab_adjust_rcol( d->line, leading );
  634.             *rcol = leading;
  635.          } else
  636.             *rcol = 0;
  637.          *r = *rcol;
  638.          if (mode.inflate_tabs)
  639.             *r = entab_adjust_rcol( d->line, d->len, *rcol );
  640.       }
  641.    }
  642.    *rline = rl;
  643.    *bin_offset = bo;
  644.    return( d );
  645. }
  646.  
  647.  
  648. /*
  649.  * Name:    show_diff_window
  650.  * Purpose: update the contents of a diff window
  651.  * Date:    October 31, 1992
  652.  * Passed:  win:  pointer to window
  653.  */
  654. void show_diff_window( WINDOW *win )
  655. {
  656.    if (win->file_info->dirty == LOCAL)
  657.       display_current_window( win );
  658.    else
  659.       show_curl_line( win );
  660.    show_line_col( win );
  661.    make_ruler( win );
  662.    show_ruler( win );
  663.    show_ruler_pointer( win );
  664.    win->file_info->dirty = FALSE;
  665. }
  666.  
  667.  
  668. /*
  669.  * Name:    verify_number
  670.  * Purpose: given a window number, verify the number
  671.  * Date:    October 31, 1992
  672.  * Passed:  temp:  string that contains number
  673.  *          num:   successfully converted number.
  674.  */
  675. int  verify_number( char *temp, int *num )
  676. {
  677. register file_infos *fp;
  678.  
  679.    /*
  680.     * see if string has a number.  if string does have a number, convert it.
  681.     */
  682.    if (*temp == '\0' || !isdigit( *temp ))
  683.       return( ERROR );
  684.    *num = 0;
  685.    while (isdigit( *temp ))
  686.       *num = *num * 10 + *temp++ - '0';
  687.  
  688.    /*
  689.     * now that we have a window number, see if any files have that number
  690.     */
  691.    for (fp=g_status.file_list; fp != NULL; fp=fp->next) {
  692.       if (fp->file_no == *num)
  693.          return( OK );
  694.    }
  695.    return( ERROR );
  696. }
  697.  
  698.  
  699.  
  700. /*
  701.  * Name:    verify_letter
  702.  * Purpose: given a window letter, verify the letter
  703.  * Date:    October 31, 1992
  704.  * Passed:  temp:  string that contains letter
  705.  *          let:   window letter
  706.  *          win:   pointer to window that contains letter and number
  707.  */
  708. int  verify_letter( char *temp, int *let, WINDOW **win )
  709. {
  710. register file_infos *fp;
  711. register WINDOW *wp;
  712. int  num;
  713.  
  714.    if (verify_number( temp, &num ) == OK) {
  715.       while (isdigit( *temp ))
  716.          temp++;
  717.       if (*temp == '\0' || !isalpha( *temp ))
  718.          return( ERROR );
  719.       *let = (int)tolower( *temp );
  720.       for (fp=g_status.file_list; fp != NULL; fp=fp->next) {
  721.          if (fp->file_no == num)
  722.             break;
  723.       }
  724.       for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
  725.          if (wp->file_info == fp  &&  wp->letter == *let  &&  wp->visible) {
  726.             *win = wp;
  727.             return( OK );
  728.          }
  729.       }
  730.    }
  731.    return( ERROR );
  732. }
  733.